package com.interviewbackend.service.Impl;

import com.baomidou.mybatisplus.core.assist.ISqlRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.interviewbackend.client.InformationPreprocessingClient;
import com.interviewbackend.dto.InterviewConfigDTO;
import com.interviewbackend.dto.InterviewStateDTO;

import com.interviewbackend.entity.InterviewRecord;
import com.interviewbackend.entity.InterviewSession;
import com.interviewbackend.entity.QuestionFile;
import com.interviewbackend.entity.SubQuestionFile;
import com.interviewbackend.mapper.InterviewRecordMapper;
import com.interviewbackend.mapper.QuestionFileMapper;
import com.interviewbackend.mapper.SubQuestionFileMapper;
import com.interviewbackend.service.InterviewFlowService;
import com.interviewbackend.service.InterviewRecordService;
import com.interviewbackend.service.InterviewSessionService;
import com.interviewbackend.service.SubQuestionService;
import com.interviewbackend.util.GenerateSubQuestions;
import com.interviewbackend.util.PdfUtil;
import com.interviewbackend.util.PromptBuilder;
import com.interviewbackend.util.ResumeParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.core.type.TypeReference;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class InterviewFlowServiceImpl implements InterviewFlowService {

    @Autowired private RedisTemplate<String, Object> redisTemplate;
    @Autowired private ResumeParser resumeParser;
    @Autowired private SubQuestionService subQuestionService;
    @Autowired private InterviewSessionService interviewSessionService;
    @Autowired private PromptBuilder promptBuilder;
    @Autowired private InterviewRecordMapper interviewRecordMapper;
    @Autowired private ObjectMapper objectMapper;
    @Autowired private QuestionFileMapper questionFileMapper;
    @Autowired private GenerateSubQuestions questionGenerationClient;
    @Autowired private InterviewRecordService interviewRecordService;
    @Autowired private SubQuestionFileMapper subQuestionFileMapper;

    @Autowired private StringRedisTemplate stringRedisTemplate;
    private static final String MANUAL_QUESTION_KEY_PREFIX = "interview:manual_question:";


    @Override
    public Map<String, Object> processResume(Long userId, MultipartFile file) throws IOException {
        // 1. 保存简历 PDF 文件到 Redis
        byte[] fileBytes = file.getBytes();
        redisTemplate.opsForValue().set("resume:file:" + userId, fileBytes, Duration.ofMinutes(30));
        // 2. 解析简历文本
        String resumeText = PdfUtil.extractText(fileBytes);
        // 3. 调 GPT 提取关键词 + 岗位类型
        List<String> keywords = resumeParser.extractKeywords(resumeText);
        String jobType = resumeParser.detectJobType(resumeText);
        // 4. 缓存信息
        redisTemplate.opsForValue().set("resume:keywords:" + userId,
                objectMapper.writeValueAsString(keywords), Duration.ofMinutes(30));
        redisTemplate.opsForValue().set("resume:jobType:" + userId, jobType, Duration.ofMinutes(30));
        // 5. 立即创建一条面试会话记录，生成 interviewId
        InterviewSession session = new InterviewSession();
        session.setUserId(userId);
        session.setJobType(jobType);
        session.setStatus("initialized");
        session.setResumeKeywords(objectMapper.writeValueAsString(keywords));
        session.setCreatedAt(LocalDateTime.now());
        interviewSessionService.save(session);
        // 6. 返回关键词、岗位类型、interviewId 给前端
        Map<String, Object> result = new HashMap<>();
        result.put("interviewId", session.getId());
        result.put("keywords", keywords);
        result.put("jobType", jobType);
        return result;
    }

    @Override
    public void generateSubQuestionSet(Long interviewId) throws IOException {
        InterviewSession session = interviewSessionService.getById(interviewId);
        Long userId = session.getUserId();

        // 从 Redis 获取关键词
        String keywordsJson = (String) redisTemplate.opsForValue().get("resume:keywords:" + userId);
        List<String> keywords = objectMapper.readValue(keywordsJson, new TypeReference<List<String>>() {});

        // 从 Redis 获取职位类型
        String jobType = (String) redisTemplate.opsForValue().get("resume:jobType:" + userId);

        if (keywords == null || jobType == null) {
            throw new IllegalStateException("请先完成简历上传和关键词提取");
        }
        redisTemplate.delete("resume:keywords:" + userId);
        redisTemplate.delete("resume:jobType:" + userId);

        // 从数据库获取主题库信息（题库文件）
        QuestionFile questionFile = questionFileMapper.selectByCategory(jobType);
        if (questionFile == null) {
            throw new IllegalStateException("未找到对应的题库文件");
        }

        // 获取题库文件内容
        String content = new String(questionFile.getContent(), StandardCharsets.UTF_8);

        // 调用 SubQuestionService 生成子题库，并传递题库内容
        byte[] subQuestions = subQuestionService.generateSubQuestionFile(keywords, jobType, content);

        // 保存生成的子问题文件
        String fileName = "sub_questions_" + interviewId + ".json";
        subQuestionService.saveSubQuestionFile(interviewId, subQuestions, fileName, keywords);
    }


    @Override
    public void configureInterview(InterviewConfigDTO dto) throws IOException {
        InterviewSession session = interviewSessionService.getById(dto.getInterviewId());
        if (session == null) throw new IllegalArgumentException("面试会话不存在");

        session.setDifficulty(dto.getDifficulty());
        session.setStyle(dto.getStyle());

        // 保存面试风格到缓存中
        String styleName = dto.getStyle();
        String styleKey = null;
        if (styleName == null) {
            styleKey = "sambert-zhimiao-emo-v1";
        } else if ("亲和友好型".equals(styleName.trim())) {
            styleKey = "sambert-zhimiao-emo-v1";
        } else if ("睿智冷静型".equals(styleName.trim())) {
            styleKey = "sambert-zhiya-v1";
        } else if ("自然流畅型".equals(styleName.trim())) {
            styleKey = "sambert-zhishuo-v1";
        } else if ("魅力演讲型".equals(styleName.trim())) {
            styleKey = "sambert-zhinan-v1";
        } else {
            styleKey = "sambert-zhimiao-emo-v1";
        }
        redisTemplate.opsForValue().set("interview:style:" + dto.getInterviewId(), styleKey, Duration.ofMinutes(30));

        session.setRoundIndex(1);
        session.setCurrentQuestionIndex(1);
        session.setNeedFollowUp(false);

        session.setPhasesJson(objectMapper.writeValueAsString(dto.getPhaseCountMap().keySet()));
        session.setPhaseCountJson(objectMapper.writeValueAsString(dto.getPhaseCountMap().values()));
        interviewSessionService.updateById(session);
    }


    @Override
    public String generateNextQuestion(Long interviewId) {
        // ✅ Step 0: 判断是否有人工题缓存
        String manualKey = MANUAL_QUESTION_KEY_PREFIX + interviewId;
        String manualQuestion = stringRedisTemplate.opsForValue().get(manualKey);
        if (manualQuestion != null) {
            // 读取当前面试 session
            InterviewSession session = interviewSessionService.getById(interviewId);
            if (session == null) throw new IllegalArgumentException("面试会话不存在");

            // 构建面试记录
            InterviewRecord manualRecord = new InterviewRecord();
            manualRecord.setInterviewId(interviewId);
            manualRecord.setIsAi(false);  // 人工题
            manualRecord.setIsFollowUp(false);
            manualRecord.setRoundIndex(session.getRoundIndex());
            manualRecord.setQuestionIndex(session.getCurrentQuestionIndex());
            manualRecord.setQuestionText(manualQuestion);

            interviewRecordService.save(manualRecord);
            stringRedisTemplate.delete(manualKey); // 删除缓存
            return manualQuestion;
        }

        InterviewSession session = interviewSessionService.getById(interviewId);
        if (session == null) throw new IllegalArgumentException("面试会话不存在");

        int roundIndex = session.getRoundIndex();
        if (roundIndex > 5) return "面试结束";

        // 获取当前阶段应有的题数
        int currentPhaseCount = getCurrentPhaseQuestionCount(session);
        List<InterviewRecord> recordList = interviewRecordMapper.selectList(
                new QueryWrapper<InterviewRecord>()
                        .eq("interview_id", interviewId)
                        .eq("round_index", roundIndex)
                        .eq("is_ai", true)
                        .eq("is_follow_up", false)
        );
        int currentRecordCount = recordList.size();

        InterviewRecord newRecord = new InterviewRecord();
        newRecord.setInterviewId(interviewId);
        newRecord.setIsAi(true);

        if (currentRecordCount >= currentPhaseCount) {
            session.setRoundIndex(session.getRoundIndex() + 1);
            session.setCurrentQuestionIndex(1);

            if (session.getRoundIndex() > 5) {
                return "面试结束";
            }

            // 更新 session 进入下一阶段
            interviewSessionService.updateById(session);
            newRecord.setRoundIndex(session.getRoundIndex());
            newRecord.setQuestionIndex(session.getCurrentQuestionIndex());
        } else {
            // 本阶段继续
            interviewSessionService.updateById(session);

            newRecord.setRoundIndex(session.getRoundIndex());
            newRecord.setQuestionIndex(session.getCurrentQuestionIndex());

            if (Boolean.TRUE.equals(session.getNeedFollowUp())) { // 生成追问问题
                // 获取上一条记录（不区分 AI 或追问）
                InterviewRecord lastRecord = interviewRecordMapper.selectList(
                        new QueryWrapper<InterviewRecord>()
                                .eq("interview_id", interviewId)
                                .orderByDesc("id")
                                .last("LIMIT 1")
                ).stream().findFirst().orElse(null);

                if (lastRecord == null) {
                    return "【追问失败：未找到上一条记录】";
                }

                // 构建追问 prompt
                String followUpPrompt = promptBuilder.buildFollowUpPrompt(session, lastRecord);

                // 调用模型生成追问问题
                String followUpQuestion = questionGenerationClient.generateQuestionFromPrompt(followUpPrompt);

                // 设置新记录内容
                newRecord.setIsFollowUp(true);
                newRecord.setQuestionText(followUpQuestion);
                interviewRecordService.save(newRecord);
                // 关闭追问状态
                session.setNeedFollowUp(false);
                interviewSessionService.updateById(session);

                return followUpQuestion;
            }

        }

        newRecord.setIsFollowUp(false);

        // ✅ 构建问题历史（仅本阶段已提过的非追问 AI 提问）
        List<InterviewRecord> roundRecords = interviewRecordMapper.selectList(
                new QueryWrapper<InterviewRecord>()
                        .eq("interview_id", interviewId)
                        .eq("round_index", roundIndex)
                        .eq("is_ai", true)
                        .eq("is_follow_up", false)
        );

        List<String> questionHistory = roundRecords.stream()
                .map(InterviewRecord::getQuestionText)
                .collect(Collectors.toList());

        // ✅ 获取子题库内容
        SubQuestionFile subQuestionFile = subQuestionFileMapper.selectByInterviewId(interviewId);
        String subQuestionContent = "";
        if (subQuestionFile != null && subQuestionFile.getContent() != null) {
            subQuestionContent = new String(subQuestionFile.getContent(), StandardCharsets.UTF_8);
        }

        // ✅ 构建 prompt
        String prompt = promptBuilder.buildNormalQuestionPrompt(session, subQuestionContent, questionHistory);
        // ✅ 调用模型生成问题
        String question = questionGenerationClient.generateQuestionFromPrompt(prompt);
        // ✅ 设置问题内容
        newRecord.setQuestionText(question);
        interviewRecordService.save(newRecord);

        return question;
    }

    // 获取设定题数
    private int getCurrentPhaseQuestionCount(InterviewSession session) {
        try {
            List<Integer> phaseCounts = objectMapper.readValue(
                    session.getPhaseCountJson(), new TypeReference<List<Integer>>() {}
            );
            int roundIndex = session.getRoundIndex(); // 从 1 开始计数
            if (roundIndex >= 1 && roundIndex <= phaseCounts.size()) {
                return phaseCounts.get(roundIndex - 1); // List 从 0 开始
            } else {
                throw new IllegalStateException("roundIndex 超出阶段范围！");
            }
        } catch (Exception e) {
            throw new IllegalStateException("解析 phaseCountJson 失败", e);
        }
    }

}
